package com.dex4d.ui.wallet.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.dex4d.BuildConfig;
import com.dex4d.R;
import com.dex4d.constants.IConstants;
import com.dex4d.core.AppToolBarBaseActivity;
import com.dex4d.core.CustomApplication;
import com.dex4d.core.http.DefaultTransformer;
import com.dex4d.core.http.JsonApiWrapper;
import com.dex4d.core.subscribers.ProgressSubscriber;
import com.dex4d.model.AssetModel;
import com.dex4d.model.HttpResult;
import com.dex4d.model.RequestParam;
import com.dex4d.model.User;
import com.dex4d.ui.demo.HomeActivity;
import com.dex4d.ui.main.activity.TradeConfirmActivity;
import com.dex4d.ui.main.model.TradeResult;
import com.dex4d.ui.qr.EasyAuthActivity;
import com.dex4d.ui.qr.EasyCaptureActivity;
import com.dex4d.ui.qr.model.QRResult;
import com.dex4d.ui.wallet.model.WalletTx;
import com.dex4d.utils.Arith;
import com.dex4d.utils.BaseUtils;
import com.dex4d.utils.Commons;
import com.dex4d.utils.DecimalInputFilter;
import com.dex4d.utils.EthWalletUtil;
import com.framework.bigdecimalutils.DoubleFormatTool;
import com.king.zxing.Intents;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.web3j.crypto.WalletUtils;
import org.web3j.utils.Convert;

import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import butterknife.BindView;
import butterknife.OnClick;
import rx.Observable;
import rx.functions.Func1;

/**
 * Created by chengyuchun on 2018/10/24.
 */
public class WalletSendActivity extends AppToolBarBaseActivity {
    private String TAG = WalletSendActivity.this.getClass().getSimpleName();

    @BindView(R.id.tv_token_name)
    TextView mTvTokenName;

    @BindView(R.id.tv_token_balance)
    TextView mTvTokenBalance;

    @BindView(R.id.rl_select_token)
    RelativeLayout mRlSelectToken;

    @BindView(R.id.tv_receive_address)
    EditText mEtToAddress;

    @BindView(R.id.et_send_number)
    EditText mEtSendNumber;

    @BindView(R.id.tv_max)
    TextView mTvMax;

    @BindView(R.id.btn_send)
    Button btn_send;

    @BindView(R.id.img_qrcode)
    ImageView img_qrcode;

    private AssetModel mAssetModel;
    private int mNonceId = 0;
    private BigInteger mGasPrice;

    public static void start(Activity activity) {
        Intent intent = new Intent(activity, WalletSendActivity.class);
        activity.startActivity(intent);
    }

    public static void start(Activity activity, String address) {
        Intent intent = new Intent(activity, WalletSendActivity.class);
        intent.putExtra("Address", address);
        activity.startActivity(intent);
    }

    @Override
    protected void initToolbar() {
        showBackView();
        showTitle(getString(R.string.send));
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_wallet_send;
    }

    @Override
    protected void initVariables() {
        EventBus.getDefault().register(this);

        mTvTokenBalance.setText(String.format(getString(R.string.wallet_balance), "", ""));
        mRlSelectToken.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openActivity(SelectTokenActivity.class);
            }
        });

        mTvMax.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mAssetModel != null)
                    mEtSendNumber.setText(mAssetModel.balance);
            }
        });

        TextWatcher textWatcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (mTvTokenName.getText().length() > 0
                        && !mTvTokenName.getText().equals(getString(R.string.select_token))
                        && mEtToAddress.getText().length() > 0
                        && mEtSendNumber.getText().length() > 0) {
                    btn_send.setClickable(true);
                    btn_send.setBackgroundResource(R.drawable.btn_blue_clickable_bg);
                    btn_send.setTextColor(getResources().getColor(R.color.white));
                } else {
                    btn_send.setClickable(false);
                    btn_send.setBackgroundResource(R.drawable.btn_blue_unclick_bg);
                    btn_send.setTextColor(getResources().getColor(R.color.gray_B7C5CA));
                }
            }
        };

        mTvTokenName.addTextChangedListener(textWatcher);
        mEtToAddress.addTextChangedListener(textWatcher);
        mEtSendNumber.addTextChangedListener(textWatcher);
        mEtSendNumber.setFilters(new InputFilter[] {new DecimalInputFilter()});

        btn_send.setClickable(false); //初始不可点击

        String address = getIntent().getStringExtra("Address");
        if (!TextUtils.isEmpty(address)) {
            mEtToAddress.setText(address);
        }
    }

    @Override
    protected void loadData() {
        initGasPrice();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(AssetModel event) {
        mAssetModel = event;
        mTvTokenName.setText(mAssetModel.symbol.toUpperCase());
        updateAsset(mAssetModel);
    }

    //更新余额
    private void updateAsset(final AssetModel assetModel) {
        if (assetModel == null) {
            return;
        } else {
            final RequestParam requestParam = new RequestParam();
            requestParam.setId(0);
            requestParam.setJsonrpc(IConstants.JSON_RPC_VERSION);
            if (IConstants.ETH_SYMBOL.equalsIgnoreCase(assetModel.symbol)) {
                //查询以太余额调用此接口
                requestParam.setMethod(IConstants.CONTRACTSERVICE_GETBALANCE);
                requestParam.setParams(Collections.singletonList(assetModel.address));
            } else {
                //查询其他代币余额调用此接口
                requestParam.setMethod(IConstants.CONTRACTSERVICE_ERC20BALANCE);
                List<String> paramsList = new ArrayList<String>();
                paramsList.add(assetModel.contracAddress);
                paramsList.add(assetModel.address);
                requestParam.setParams(paramsList);
            }

            JsonApiWrapper
                    .serviceApi()
                    .requestByParam(requestParam)
                    .compose(new DefaultTransformer<HttpResult<String>>())  //取网络数据这个函数不能少，这是线程切换
                    .subscribe(new ProgressSubscriber<HttpResult<String>>(this, false) {
                        @Override
                        public void onNext(HttpResult<String> result) {
                            assetModel.balance = BaseUtils.hexToEtherUnit(result.getResult()); //unit ether
                            mTvTokenBalance.setText(String.format(getString(R.string.wallet_balance), mAssetModel.balance, mAssetModel.symbol.toUpperCase()));
                        }
                    });
        }
    }


    private void initGasPrice(){
        final RequestParam gasParam = new RequestParam();
        gasParam.setId(4);
        gasParam.setJsonrpc(IConstants.JSON_RPC_VERSION);
        gasParam.setMethod(IConstants.CONTRACTSERVICE_GASPRICE);
        gasParam.setParams(Collections.singletonList(User.getInstance().getAddress()));

        //gas price
        JsonApiWrapper
                .serviceApi()
                .requestByParam(gasParam)
                .compose(new DefaultTransformer<HttpResult<String>>())  //取网络数据这个函数不能少，这是线程切换
                .subscribe(new ProgressSubscriber<HttpResult<String>>(this, false) {
                    @Override
                    public void onNext(HttpResult<String> result) {
                        //服务器传过来的 GasPrice 是十进制
                        mGasPrice =  new BigInteger(result.getResult());
                    }
                });
    }

    private String calculateGasFee(String symbol){
        if(mGasPrice == null)
            return "0.0";

        BigInteger gasLimit = new BigInteger("eth".equalsIgnoreCase(symbol)?  "21000" : "144000");
        return Convert.fromWei(mGasPrice.multiply(gasLimit).toString(), Convert.Unit.ETHER).setScale(6, RoundingMode.CEILING).toString();
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    @OnClick(R.id.btn_send)
    public void onViewClick() {
        String toAddress = mEtToAddress.getText().toString(); //转账地址
        //校验地址格式
        if(!BaseUtils.isEthAddress(toAddress)){
            Toast.makeText(this,getString(R.string.address_invalid),Toast.LENGTH_SHORT).show();
            return;
        }

        String value = mEtSendNumber.getText().toString(); //转账金额
        if (Arith.sub(Double.parseDouble(mAssetModel.balance),
                Double.parseDouble(mEtSendNumber.getText().toString())) < 0) {
            Toast.makeText(this, getString(R.string.balance_remind), Toast.LENGTH_SHORT).show();
            return;
        }else if(mAssetModel.symbol.equalsIgnoreCase(IConstants.ETH_SYMBOL)
                && Arith.sub(Double.parseDouble(mAssetModel.balance),
                Double.parseDouble(mEtSendNumber.getText().toString())) == 0){
            value = Arith.sub(Double.parseDouble(mAssetModel.balance),
                    Double.parseDouble(calculateGasFee(mAssetModel.symbol)),6) + "";
        }


        Bundle bundle = new Bundle();
        bundle.putInt(Commons.BUNDLE_KEYS.TRADE_TYPE,TradeResult.FLAG_TRANSFER);
        bundle.putString(Commons.BUNDLE_KEYS.TO_SYMBOL,mTvTokenName.getText().toString().toLowerCase());
        bundle.putString(Commons.BUNDLE_KEYS.TO_ADDRESS,toAddress); //转入地址
        if(!mAssetModel.symbol.equalsIgnoreCase(IConstants.ETH_SYMBOL)){
            bundle.putString(Commons.BUNDLE_KEYS.TOKEN_CONTRACT_ADDRESS,mAssetModel.contracAddress); //代币的合约地址
        }
        bundle.putString(Commons.BUNDLE_KEYS.COIN_AMOUNT,value); //转账数额
        bundle.putString(Commons.BUNDLE_KEYS.ASSET_BALANCE,mAssetModel.balance); //资产余额
        bundle.putString(Commons.BUNDLE_KEYS.GAS_CONSUMPTION,calculateGasFee(mAssetModel.symbol));
        openActivity(TradeConfirmActivity.class,bundle);


        //下面默认数据格式是正确的
//        sendTranscation();
    }


    //生成签名数据
    private String genarateSignData(int nonceId, String gasPrice) {
        if (mAssetModel == null) {
            return null;
        }
        String toAddress = mEtToAddress.getText().toString(); //转账地址
        String value = mEtSendNumber.getText().toString(); //转账金额
        String password = User.getInstance().getPassphrase(); //解析密码

        Log.i(TAG, "gasPrice:" + gasPrice + ",toAddress:" + toAddress + ",value:" + value + ",mNonceId" + nonceId);
        String sign = "";
        if (mAssetModel.symbol.equalsIgnoreCase(IConstants.ETH_SYMBOL)) {
            sign = EthWalletUtil.getTransactionSigned(toAddress, nonceId, value, gasPrice, password);
        } else {
            String contract = mAssetModel.contracAddress;
            sign = EthWalletUtil.getTokenTransactionSigned(contract, toAddress, nonceId, value, gasPrice, password);
        }

        return sign;
    }


    /**
     * 发送交易
     */
    private void sendTranscation() {
        final RequestParam requestParam = new RequestParam();
        requestParam.setId(1);
        requestParam.setJsonrpc(IConstants.JSON_RPC_VERSION);
        requestParam.setMethod(IConstants.CONTRACTSERVICE_GETNONCE);
        requestParam.setParams(Collections.singletonList(User.getInstance().getAddress()));

        final WalletTx walletTx = WalletTx.createOut();


        JsonApiWrapper
                .serviceApi()
                .requestByParam(requestParam) //第一步 取出nonceid
                .flatMap(new Func1<HttpResult<String>, Observable<HttpResult<String>>>() {
                    @Override
                    public Observable<HttpResult<String>> call(HttpResult<String> result) {
                        mNonceId = Integer.parseInt(result.getResult());

                        walletTx.nonce = result.getResult();

                        requestParam.setId(2);
                        requestParam.setMethod(IConstants.CONTRACTSERVICE_GASPRICE);
                        return JsonApiWrapper.serviceApi().requestByParam(requestParam); //第二步 获取gas price
                    }
                })
                .flatMap(new Func1<HttpResult<String>, Observable<HttpResult<String>>>() {
                    @Override
                    public Observable<HttpResult<String>> call(HttpResult<String> result) {
                        String gasPrice = result.getResult();
                        String signData = genarateSignData(mNonceId, gasPrice); //第三步 生成签名数据

                        walletTx.gasPrice = gasPrice;
                        walletTx.to = mEtToAddress.getText().toString();
                        walletTx.data = signData;
                        walletTx.value = mEtSendNumber.getText().toString();
                        walletTx.balance = DoubleFormatTool.sub(mAssetModel.balance, walletTx.value, 6);//余额减去发送量

                        requestParam.setId(3);
                        requestParam.setMethod(IConstants.CONTRACTSERVICE_SENDRAWTRANSACTION);
                        requestParam.setParams(Collections.singletonList(signData));
                        return JsonApiWrapper.serviceApi().requestByParam(requestParam); //第四步 发送广播
                    }
                })

                .flatMap(new Func1<HttpResult<String>, Observable<String>>() {
                    @Override
                    public Observable<String> call(HttpResult<String> result) {

                        String gaslimit = mAssetModel.symbol.equalsIgnoreCase(IConstants.ETH_SYMBOL) ? "21000" : "144000";

                        String hash = result.getResult();

                        walletTx.symbol = mAssetModel.symbol;
                        walletTx.gasLimit = gaslimit;
                        walletTx.txHash = hash;
                        walletTx.txReceiptStatus = 2;

                        CustomApplication.getDb().txDao().insertTx(walletTx);//将交易保存到本地

                        return JsonApiWrapper.serviceApi().addtx(BuildConfig.TX_URL_API + "/addtx", walletTx);
                    }
                })
                .map(new Func1<String, QRResult>() {
                    @Override
                    public QRResult call(String s) {
                        return new QRResult(walletTx.txHash);
                    }
                })
                //这是线程切换，切换成主线程，3个异步过程中只要有网络异常或返回错误，即会回调onError方法
                .compose(new DefaultTransformer<QRResult>())
                .subscribe(new ProgressSubscriber<QRResult>(this, true) {
                    @Override
                    public void onNext(QRResult result) {
                        String gaslimit = mAssetModel.symbol.equalsIgnoreCase(IConstants.ETH_SYMBOL) ? "21000" : "144000";
                        Bundle bundle = new Bundle();
                        bundle.putString(Commons.BUNDLE_KEYS.AMOUNT, mEtSendNumber.getText().toString() + " " + mAssetModel.symbol);
                        bundle.putString(Commons.BUNDLE_KEYS.GAS_LIMIT, gaslimit);

                        String hash = result.txhash;
                        bundle.putString(Commons.BUNDLE_KEYS.TRANS_HASH, hash.substring(0, 5) + "..." + hash.substring(hash.length() - 7, hash.length()));
                        openActivity(SendSuccessActivity.class, bundle);
                    }
                });
    }

    @OnClick(R.id.img_qrcode)
    public void qrcode() {
        EasyCaptureActivity.start(this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
            if (requestCode == HomeActivity.REQUEST_CODE_SCAN) {//扫码
                String result = data.getStringExtra(Intents.Scan.RESULT);
                if (TextUtils.isEmpty(result)) return;
                if (WalletUtils.isValidAddress(result)) {//跳转到转账页面
//                    WalletSendActivity.start(this,result);
                    mEtToAddress.setText(result);
                } else {
                    EasyAuthActivity.start(this, result);
                }
            }
        }
    }
}
